﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTO;
using BUS;
using System.Drawing;

namespace RectanglePacker
{
    class Program
    {
        static void Main(string[] args)
        {
            SpriteDTO sprite = SpriteBUS.Load("objects.xml");

            List<FModule> fmodules = new List<FModule>();
            for (int i = 0; i < sprite.Modules.Count; i++)
            {
                FModule fmodule = new FModule();
                fmodule.Module = sprite.Modules[i].Clone();
                fmodule.Module.W += 2;
                fmodule.Module.H += 2;
                fmodules.Add(fmodule);
            }

            int n;
            int totalPixels = 0;
            for (n = 0; n < fmodules.Count; n++)
            {
                totalPixels += (fmodules[n].Module.W + 2) * (fmodules[n].Module.H + 2);
            }

            int ixSize = 0;
            int texWidth = 32;
            int texHeight = 32;
            while (true)
            {
                if (totalPixels <= texWidth * texHeight)
                {
                    break;
                }
                GetNextTextureSize(ref texWidth, ref  texHeight, ixSize);
                ixSize++;
            }

            //sort

            for (int i = 0; i < fmodules.Count - 1; i++)
                for (int j = i + 1; j < fmodules.Count; j++)
                {
                    if (fmodules[i].Module.NumPixels < fmodules[j].Module.NumPixels)
                    {
                        FModule tmpFModule = fmodules[i];
                        fmodules[i] = fmodules[j];
                        fmodules[j] = tmpFModule;
                    }
                }
            //

            while (!BinPack(fmodules, texWidth, texHeight))
            {
                GetNextTextureSize(ref texWidth, ref  texHeight, ixSize);
                ixSize++;
            }

            //Draw Image
            Bitmap bitmap = new Bitmap(texWidth, texHeight);
            Graphics graphic = Graphics.FromImage(bitmap);
            for (n = 0; n < fmodules.Count; n++)
            {
                DrawToBitmap(graphic, fmodules[n],sprite.ImageInfo[0], texWidth, texHeight);
            }
            


            bitmap.Save("abc.png");

        }

        static void GetNextTextureSize(ref int texWidth, ref int texHeight, int ixSize)
        {
            if (ixSize % 2 == 1)
                texHeight *= 2;
            else
                texWidth *= 2;
            if (texWidth > 1024 || texHeight > 1024)
            {
                //throw RacException("to many images to fit in one texture");
            }
        }

        static bool BinPack(List<FModule> m_listBitmapChar, int texWidth, int texHeight)
        {
            TreeNode pTreeNode = new TreeNode();
            pTreeNode.Set(0, 0, texWidth, texHeight);
            for (int n = 0; n < m_listBitmapChar.Count; n++)
            {
                if (!pTreeNode.Add(m_listBitmapChar[n]))
                {
                    return false;
                }
            }
            return true;
        }

        static void DrawToBitmap(Graphics g, FModule fmodule, ImageInfo imageInfo, int texWidth, int texHeight)
        {
            int posX = fmodule.Ox + 1;
            int posY = fmodule.Oy + 1;

            Rectangle srcRec = new Rectangle(fmodule.Module.X, fmodule.Module.Y, fmodule.Module.W - 2, fmodule.Module.H - 2);
            Rectangle desRec = new Rectangle((posX), (posY), (fmodule.Module.W - 2), (fmodule.Module.H - 2));
         
            //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
            //g.FillRectangle(Brushes.Gray, desRec);
            g.DrawImage(imageInfo.Image, desRec, srcRec.X, srcRec.Y, srcRec.Width, srcRec.Height, GraphicsUnit.Pixel, imageInfo.ImageAttr);
        }
    }
}
